/*	$Id: card.h 85 2007-01-04 22:18:56Z phrakt $	*/
/*
 * Copyright (c) 2006 Jean-Francois Brousseau <phrakt@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/types.h>

#include <stdlib.h>
#include <unistd.h>

#ifdef USE_THREADS
#include <pthread.h>

static void*  mtg_game_thread  (void *);
#endif

#include "mtg.h"
#include "game.h"
#include "player.h"



struct mtg_game {
	volatile enum mtg_game_state  mg_status;

	mtg_player_t                **mg_players;
	int                           mg_plcount;

	int                           mg_winner;

#ifdef USE_THREADS
	pthread_t                     mg_thrid;

	pthread_mutex_t               mg_lock;
	pthread_cond_t                mg_cond;
#endif
};






/*
 * mtg_game_create()
 */
mtg_game_t*
mtg_game_create(void)
{
	int ret;
	mtg_game_t *game;

	if ((game = malloc(sizeof(*game))) == NULL) {
		return (NULL);
	}

	memset(game, 0, sizeof(*game));

	game->mg_status = MTG_GAME_WAITING;

#ifdef USE_THREADS
	ret = pthread_mutex_init(&game->mg_lock, NULL);
	ret = pthread_cond_init(&game->mg_cond, NULL);
#endif

	return (game);
}

/*
 * mtg_game_free()
 *
 */
void
mtg_game_free(mtg_game_t *game)
{
#ifdef USE_THREADS
	(void)pthread_mutex_destroy(&game->mg_lock);
#endif

	free(game);
}

/*
 * mtg_game_start()
 *
 * Start the game.
 * If this library was compiled with thread support, the function returns
 * right after the game thread has started running.  Otherwise, the function
 * does not return until the game is finished.
 * Returns 0 if the game ran correctly, or -1 if an error occurred.
 */
int
mtg_game_start(mtg_game_t *game)
{
	int ret = 0;

#ifdef USE_THREADS
	pthread_t tid;

	ret = pthread_create(&game->mg_thrid, NULL, mtg_game_thread, game);
	if (ret == 0) {
	} else /* if we failed to start a thread, run the game synchronously */
#else
		ret = mtg_game_run(game);
#endif

	return (ret);
}

#ifdef USE_THREADS
/*
 * mtg_game_thread()
 *
 */
static void*
mtg_game_thread(void *arg)
{
	int ret;

	ret = mtg_game_run((mtg_game_t *)arg);

	return (NULL);
}
#endif

/*
 * mtg_game_run()
 *
 * The ugly details.
 */
int
mtg_game_run(mtg_game_t *g)
{
	int turn, pcount = g->mg_plcount;
	mtg_player_t *curplayer;

	turn = 0;

	while (pcount > 1) {
		curplayer = g->mg_players[turn % pcount];

		printf("Player %d's turn: %s\n", (turn % pcount) + 1,
		    mtg_player_getname(curplayer));
	}

	return (0);
}
